(function(host){

var eventNames = 'ontouchstart' in document ? {
	mousedown: 'touchstart',
	mousemove: 'touchmove',
	mouseup: 'touchend'
} : {
	mousedown: 'mousedown',
	mousemove: 'mousemove',
	mouseup: 'mouseup'
};

function query(q, all, startElement){
	return typeof(q) == 'string'
		? (startElement || document)[!all ? 'querySelector' : 'querySelectorAll'](q)
		: (!all ? (q || null) : (q || []));
}
function fun(v){
	return typeof(v) == 'function';
}

function addEvent(el, name, callback, useCapture){
	if(typeof(el) == 'string') el = query(el);
	if(name in eventNames){
		name = eventNames[name];
	}
	el.addEventListener(name, callback, useCapture);
}
function removeEvent(el, name, callback){
	if(typeof(el) == 'string') el = query(el);
	if(name in eventNames){
		name = eventNames[name];
	}
	el.removeEventListener(name, callback);
}
function getSingleEvent(e){
	if('changedTouches' in e){
		return e.changedTouches[0];
	}
	return e;
}
function getSingleEventPostion(e){
	e = getSingleEvent(e);
	return [e.clientX, e.clientY];
}
function getSingleEventPostionINT(e){
	e = getSingleEvent(e);
	return [e.clientX >> 0, e.clientY >> 0];
}

function isObject(o){
	return Object.prototype.toString.call(o) === '[object Object]';
}
function isArray(o){
	return Object.prototype.toString.call(o) === '[object Array]';
}
function isFunction(v){
	return typeof(v) == 'function';
}
function isString(v){
	return typeof(v) == 'string';
}

function cloneObject(o){
	if(!o || !isObject(o)) return o;
	var r = {};
	for(var p in o){
		if(isObject(o[p])){
			r[p] = cloneObject(o[p]);
		} else {
			r[p] = o[p];
		}
	}
	return r;
}

//a overwrite b;
function mixObject(a, b){
	if(isObject(a) && isObject(b)){
		var c = cloneObject(b);
		for(var p in a){
			c[p] = mixObject(a[p], b[p]);
		}
		return c;
	} else {
		return cloneObject(a);
	}
}

// a -> b
function copyTo(a, b){
	if(!isObject(a) || !isObject(b)) return;
	for(var p in a){
		if(isObject(a[p])){
			if(!isObject(b[p])){
				b[p] = {};
			}
			copyTo(a[p], b[p]);
		} else if(isObject(b[p])){
			continue;
		} else {
			b[p] = a[p];
		}
	}
}

function toInt(v){
	return v >> 0;
}

function each(o, fn){
	for(var p in o){
		if(fn(o[p], p, o)) return;
	}
}
function EACH(a, fn){
	var i = 0;
	while(i < a.length){
		if(fn(a[i], i, a)) return;
		i++;
	}
}
function HCAE(a, fn){
	var i = a.length - 1;
	while(i >= 0){
		if(fn(a[i], i, a)) return;
		i--;
	}
}

function isNumberStyle(name){
	return /opacity|zoom|z\-index|zIndex/.test(name);
}

function obj2style(style, o, V){
	if(isObject(o)){
		each(o, function(v, p){
			setStyle(style, p, v);
		});
	} else if(arguments.length == 3){
		setStyle(style, o, V);
		return;
	}
}

function cssPair(name, value){
	if(typeof(value) == 'number' && !isNumberStyle(name)){
		value += 'px';
	}
	value += '';
	if(name == 'background-image' 
		&& value != 'none'
		&& value.substr(0, 3) != 'url'){
		value = 'url(' + value + ')';
	}
	return name + ':' + value + ';';
}
function setStyle(style, name, value){
	if(typeof(value) == 'number' && !isNumberStyle(name)){
		value += 'px';
	}
	value += '';
	if(name == 'background-image'
		&& value != 'none'
		&& value.substr(0, 3) != 'url'){
		value = 'url(' + value + ')';
	}
	return style[name] = value;
}

function obj2css(o, V){

	if(isObject(o)){
		var arr = [];
		each(o, function(v, p){
			arr.push(cssPair(p, v))
		});
		return arr.join('');
	} else if(arguments.length == 2){
		return cssPair(o, V);
	}
}

function Class(name, base, contruct, protos){
	var fn;
	eval(
	'fn=function ' + name + '(){'
		+ (isFunction(base) ? 'base.apply(this,arguments);' : '')
		+ (isFunction(contruct) ? 'contruct.apply(this,arguments);' : '')
	+ '}'
	);
	isFunction(base) && each(base.prototype, function(v, p){
		fn.prototype[p] = v;
	});
	isObject(protos) && each(protos, function(v, p){
		fn.prototype[p] = v;
	});
	return fn;
}
function serializableTypeNS(v){
	var type = typeof(v);
	switch(type){
		case 'string':
		case 'boolean':
			return type;
		case 'number':
			var s = v + '';
			return s.indexOf('.') > -1 ? 'float' : 'int';
	}
	return false;
}

function parseValue(s, ns){
	s += '';
	switch(ns){
		case 'string':
			return s;
		case 'boolean':
			return s === 'true';
		case 'float':
			return parseFloat(s);
		case 'int':
			return parseInt(s);
	}
	return null;
}

var util = {
	parseValue: parseValue,
	serializableTypeNS: serializableTypeNS,
	Class: Class,
	EACH: EACH,
	HCAE: HCAE,
	slice: function(tar, i){
		return Array.prototype.slice.call(tar, i || 0);
	},
	invoke: function(fn, ctx, args){
		if(!isArray(args)){
			args = this.slice(arguments, 2);
		}
		return fn.apply(ctx, args);
	},
	each: each,
	$each: function(q, fn, tar){
		EACH(this.$(q, 1, tar), fn);
	},
	map: function(obj, schema){
		var o = {};
		obj && util.isObject(obj) && EACH(schema, function(key){
			if(key in obj){
				o[key] = obj[key];
			}
		});
		return o;
	},
	obj2css: obj2css,
	obj2style: obj2style,
	toInt: toInt,
	isObject: isObject,
	isArray: isArray,
	isFunction: isFunction,
	isString: isString,
	copyTo: copyTo,
	$: query,
	addEvent: addEvent,
	removeEvent: removeEvent,
	getSingleEvent: getSingleEvent,
	getSingleEventPostion: getSingleEventPostion,
	getSingleEventPostionINT: getSingleEventPostionINT,
	readAsDataURL: function(file, fn){
		var reader = new FileReader();
		reader.addEventListener('load', function onload(e){
			this.removeEventListener('load', onload);
			fn(this.result);
			reader = null;
		});
		reader.readAsDataURL(file);
	},
	getImageDataFromSrc: function(url, fn){
		var img = new Image();
		var data = { isLocal: false };
		img.addEventListener('load', function onload(e){
			this.removeEventListener('load', onload);
			data.width = this.width;
			data.height = this.height;
			data.src = this.src;
			fn(data);
		});
		img.src = url;
	},
	getImageDataFromFile: function(file, fn){
		var _ = this;
		_.readAsDataURL(file, function(base64){
			_.getImageDataFromSrc(base64, function(data){
				data.isLocal = true;
				data.type = file.type;
				data.size = file.size;
				data.name = file.name;
				data.lastModified = file.lastModified || file.lastModifiedDate;
				fn(data);
			});
		})
	},
	getImageData: function(tar, fn){
		if(typeof(tar) == 'string'){
			this.getImageDataFromSrc(tar, fn);
		} else {
			this.getImageDataFromFile(tar, fn);
		}
	}
};

host.util = util;


})(window);